home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / util / gnu / xpdf-0.8-src.lha / xpdf-0.8-src / ltk / LTKBox.cc < prev    next >
C/C++ Source or Header  |  1998-11-28  |  8KB  |  318 lines

  1. //========================================================================
  2. //
  3. // LTKBox.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. #pragma implementation
  11. #endif
  12.  
  13. #include <stdlib.h>
  14. #include <stdarg.h>
  15. #include <stddef.h>
  16. #include <X11/Xlib.h>
  17. #include <X11/Xutil.h>
  18. #include "LTKWindow.h"
  19. #include "LTKBox.h"
  20.  
  21. LTKBox::LTKBox(char *name1, int cols1, int rows1,
  22.            int left1, int right1, int top1, int bottom1,
  23.            LTKBorder border1, int xfill1, int yfill1, ...):
  24.     LTKWidget(name1, 0) {
  25.   int col, row;
  26.   va_list args;
  27.  
  28.   cols = cols1;
  29.   rows = rows1;
  30.   left = left1;
  31.   right = right1;
  32.   top = top1;
  33.   bottom = bottom1;
  34.   border = border1;
  35.   if (border == ltkBorderNone)
  36.     borderWidth = 0;
  37.   else
  38.     borderWidth = ltkBorderWidth;
  39.   xfill = xfill1;
  40.   yfill = yfill1;
  41.   contents = new LTKWidget*[cols*rows];
  42.   va_start(args, yfill1);
  43.   for (row = 0; row < rows; ++row)
  44.     for (col = 0; col < cols; ++col)
  45.       get(col, row) = va_arg(args, LTKWidget *);
  46.   va_end(args);
  47. }
  48.  
  49. LTKBox::~LTKBox() {
  50.   int col, row;
  51.  
  52.   for (col = 0; col < cols; ++col)
  53.     for (row = 0; row < rows; ++row)
  54.       delete get(col, row);
  55.   delete[] contents;
  56. }
  57.  
  58. void LTKBox::setParent(LTKWindow *parent1) {
  59.   int col, row;
  60.  
  61.   parent = parent1;
  62.   for (col = 0; col < cols; ++col)
  63.     for (row = 0; row < rows; ++row)
  64.       get(col, row)->setParent(parent1);
  65. }
  66.  
  67. void LTKBox::setCompoundParent(LTKWidget *compParent1) {
  68.   int col, row;
  69.  
  70.   compParent = compParent1;
  71.   for (col = 0; col < cols; ++col)
  72.     for (row = 0; row < rows; ++row)
  73.       get(col, row)->setCompoundParent(compParent1);
  74. }
  75.  
  76. void LTKBox::setBorder(LTKBorder border1) {
  77.   if (border1 != border) {
  78.     border = border1;
  79.     ltkDrawBorder(getDisplay(), getParent()->getXWindow(),
  80.           getBrightGC(), getDarkGC(), getBgGC(),
  81.           x, y, width, height, border);
  82.   }
  83. }
  84.  
  85. GBool LTKBox::checkFills(char **err) {
  86.   LTKWidget *widget;
  87.   LTKBox *box;
  88.   int col, row;
  89.  
  90.   // all contents of a non-1x1 box must be boxes;
  91.   // non-box widgets don't use fill flags, so just return
  92.   if (cols == 1 && rows == 1) {
  93.     widget = get(0, 0);
  94.     if (!widget->isBox())
  95.       return gTrue;
  96.   } else {
  97.     for (col = 0; col < cols; ++col) {
  98.       for (row = 0; row < rows; ++row) {
  99.     widget = get(col, row);
  100.     if (!widget->isBox()) {
  101.       *err = "contents of a non-1x1 box must be boxes";
  102.       return gFalse;
  103.     }
  104.       }
  105.     }
  106.   }
  107.  
  108.   // all xfills in a given column must be the same;
  109.   // all yfills in a given row must be the same
  110.   if (cols > 1 || rows > 1) {
  111.     for (col = 0; col < cols; ++col) {
  112.       for (row = 0; row < rows; ++row) {
  113.     box = getBox(col, row);
  114.     if (box->xfill != getBox(col, 0)->xfill) {
  115.       *err = "all xfills in a column must be the same";
  116.       return gFalse;
  117.     }
  118.     if (box->yfill != getBox(0, row)->yfill) {
  119.       *err = "all yfills in a row must be the same";
  120.       return gFalse;
  121.     }
  122.       }
  123.     }
  124.   }
  125.  
  126.   // check contents
  127.   for (col = 0; col < cols; ++col) {
  128.     for (row = 0; row < rows; ++row) {
  129.       if (!getBox(col, row)->checkFills(err))
  130.     return gFalse;
  131.     }
  132.   }
  133.  
  134.   // everything checked out ok
  135.   *err = "";
  136.   return gTrue;
  137. }
  138.  
  139. void LTKBox::layout1() {
  140.   int col, row;
  141.   int dw, dh, w1, h1;
  142.   int t1, t2;
  143.  
  144.   // do children
  145.   for (col = 0; col < cols; ++col)
  146.     for (row = 0; row < rows; ++row)
  147.       get(col, row)->layout1();
  148.  
  149.   // if there is only one child and it is not a box, just
  150.   // grab its min width and height
  151.   if (cols == 1 && rows == 1 && !get(0, 0)->isBox()) {
  152.     width = get(0, 0)->getWidth() + left + right + 2 * borderWidth;
  153.     height = get(0, 0)->getHeight() + top + bottom + 2 * borderWidth;
  154.     return;
  155.   }
  156.  
  157.   // compute min width
  158.   dw = 0;
  159.   for (col = 0; col < cols; ++col)
  160.     dw += getBox(col, 0)->getXFill();
  161.   width = 0;
  162.   w1 = 0;
  163.   for (col = 0; col < cols; ++col) {
  164.     t1 = 0;
  165.     for (row = 0; row < rows; ++row) {
  166.       if (getBox(col, row)->getXFill() > 0)
  167.     t2 = (get(col, row)->getWidth() * dw) / getBox(col, row)->getXFill();
  168.       else
  169.     t2 = get(col, row)->getWidth();
  170.       if (t2 > t1)
  171.     t1 = t2;
  172.     }
  173.     if (getBox(col, 0)->getXFill() > 0) {
  174.       if (t1 > w1)
  175.     w1 = t1;
  176.     } else {
  177.       width += t1;
  178.     }
  179.   }
  180.   width += w1 + left + right + 2 * borderWidth;
  181.  
  182.   // compute min height
  183.   dh = 0;
  184.   for (row = 0; row < rows; ++row)
  185.     dh += getBox(0, row)->getYFill();
  186.   height = 0;
  187.   h1 = 0;
  188.   for (row = 0; row < rows; ++row) {
  189.     t1 = 0;
  190.     for (col = 0; col < cols; ++col) {
  191.       if (getBox(col, row)->getYFill() > 0)
  192.     t2 = (get(col, row)->getHeight() * dh) / getBox(col, row)->getYFill();
  193.       else
  194.     t2 = get(col, row)->getHeight();
  195.       if (t2 > t1)
  196.     t1 = t2;
  197.     }
  198.     if (getBox(0, row)->getYFill() > 0) {
  199.       if (t1 > h1)
  200.     h1 = t1;
  201.     } else {
  202.       height += t1;
  203.     }
  204.   }
  205.   height += h1 + top + bottom + 2 * borderWidth;
  206. }
  207.  
  208. void LTKBox::layout2(int x1, int y1, int width1, int height1) {
  209.   int *widths, *heights;
  210.   int col, row;
  211.   int dw1, dw2, dh1, dh2;
  212.   int tx, ty;
  213.  
  214.   x = x1 + left;
  215.   y = y1 + top;
  216.   width = width1 - left - right;
  217.   height = height1 - top - bottom;
  218.  
  219.   if (cols == 1 && rows == 1 && !get(0, 0)->isBox()) {
  220.     get(0, 0)->layout2(x + borderWidth, y + borderWidth,
  221.                width - 2 * borderWidth, height - 2 * borderWidth);
  222.     return;
  223.   }
  224.  
  225.   dw1 = width - 2 * borderWidth;
  226.   dw2 = 0;
  227.   widths = new int[cols];
  228.   for (col = 0; col < cols; ++col) {
  229.     widths[col] = get(col, 0)->getWidth();
  230.     for (row = 1; row < rows; ++row) {
  231.       if (get(col, row)->getWidth() > widths[col])
  232.     widths[col] = get(col, row)->getWidth();
  233.     }
  234.     if (getBox(col, 0)->getXFill() > 0)
  235.       dw2 += getBox(col, 0)->getXFill();
  236.     else
  237.       dw1 -= widths[col];
  238.   }
  239.   if (dw2 > 0) {
  240.     for (col = 0; col < cols; ++col) {
  241.       if (getBox(col, 0)->getXFill() > 0)
  242.     widths[col] = (getBox(col, 0)->getXFill() * dw1) / dw2;
  243.     }
  244.   }
  245.  
  246.   dh1 = height - 2 * borderWidth;
  247.   dh2 = 0;
  248.   heights = new int[rows];
  249.   for (row = 0; row < rows; ++row) {
  250.     heights[row] = get(0, row)->getHeight();
  251.     for (col = 1; col < cols; ++col) {
  252.       if (get(col, row)->getHeight() > heights[row])
  253.     heights[row] = get(col, row)->getHeight();
  254.     }
  255.     if (getBox(0, row)->getYFill() > 0)
  256.       dh2 += getBox(0, row)->getYFill();
  257.     else
  258.       dh1 -= heights[row];
  259.   }
  260.   if (dh2 > 0) {
  261.     for (row = 0; row < rows; ++row) {
  262.       if (getBox(0, row)->getYFill() > 0)
  263.     heights[row] = (getBox(0, row)->getYFill() * dh1) / dh2;
  264.     }
  265.   }
  266.  
  267.   tx = x + borderWidth;
  268.   for (col = 0; col < cols; ++col) {
  269.     ty = y + borderWidth;
  270.     for (row = 0; row < rows; ++row) {
  271.       get(col, row)->layout2(tx, ty, widths[col], heights[row]);
  272.       ty += heights[row];
  273.     }
  274.     tx += widths[col];
  275.   }
  276.  
  277.   delete[] widths;
  278.   delete[] heights;
  279. }
  280.  
  281. void LTKBox::layout3() {
  282.   int col, row;
  283.  
  284.   for (col = 0; col < cols; ++col)
  285.     for (row = 0; row < rows; ++row)
  286.       get(col, row)->layout3();
  287. }
  288.  
  289. void LTKBox::map() {
  290.   int col, row;
  291.  
  292.   for (col = 0; col < cols; ++col)
  293.     for (row = 0; row < rows; ++row)
  294.       get(col, row)->map();
  295. }
  296.  
  297. void LTKBox::redraw() {
  298.   int col, row;
  299.  
  300.   ltkDrawBorder(getDisplay(), getParent()->getXWindow(),
  301.         getBrightGC(), getDarkGC(), getBgGC(),
  302.         x, y, width, height, border);
  303.   for (col = 0; col < cols; ++col)
  304.     for (row = 0; row < rows; ++row)
  305.       get(col, row)->redraw();
  306. }
  307.  
  308. void LTKBox::redrawBackground() {
  309.   int col, row;
  310.  
  311.   ltkDrawBorder(getDisplay(), getParent()->getXWindow(),
  312.         getBrightGC(), getDarkGC(), getBgGC(),
  313.         x, y, width, height, border);
  314.   for (col = 0; col < cols; ++col)
  315.     for (row = 0; row < rows; ++row)
  316.       get(col, row)->redrawBackground();
  317. }
  318.